
#include "game.hpp"
#include "gamestate/GameStateManager.hpp"
#include "PlayState.hpp"
#include "MenuState.hpp"
#include "audiere.h"

using namespace audiere;

AudioDevicePtr device( OpenDevice() );
OutputStreamPtr song( OpenSound( device, "music_level_1.mp3", false ) );

Game::Game() : m_pRoot(0), m_pTimer(0)
{}

Game::~Game()
{}

bool Game::Init()
{
	song->setVolume(0.5f);
	song->play();
	//enable logfile first of all
	Ogre::LogManager* logMgr = new Ogre::LogManager();
	m_pLog = Ogre::LogManager::getSingleton().createLog("ppr.log", true, true, false);

	m_pRoot = new Ogre::Root();

	if (!m_pRoot->restoreConfig())
		if (!m_pRoot->showConfigDialog())
			return false;

	m_pRenderWindow = m_pRoot->initialise(true, "Project Portal Ripoff - The Prototype");
	m_pViewport = m_pRenderWindow->addViewport(0);
	m_pViewport->setBackgroundColour(Ogre::ColourValue(0.0f, 0.0f, 0.0f, 1.0f));
	m_pViewport->setCamera(0);

	/*
	 * set up input
	 */
	unsigned long hWnd = 0;
	//OIS::ParamList paramList;
    m_pRenderWindow->getCustomAttribute("WINDOW", &hWnd);
    /*#if defined OIS_WIN32_PLATFORM
		paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
		paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
		paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
		paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
	#elif defined OIS_LINUX_PLATFORM
		paramList.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
		paramList.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
		paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
		paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
	#endif
    paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));*/
    m_pInputManager = OIS::InputManager::createInputSystem(hWnd);
	m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputManager->createInputObject(OIS::OISKeyboard, true));
	m_pMouse = static_cast<OIS::Mouse*>(m_pInputManager->createInputObject(OIS::OISMouse, true));

	m_pKeyboard->setEventCallback(this);
	m_pMouse->setEventCallback(this);

	OIS::MouseState &mutableMouseState = const_cast<OIS::MouseState &>(m_pMouse->getMouseState());
	mutableMouseState.width = m_pViewport->getActualWidth();
	mutableMouseState.height = m_pViewport->getActualHeight();

	Ogre::String secName, typeName, archName;
	Ogre::ConfigFile cf;
    cf.load("resources.cfg");
	
	//iterate over the sections of the resource file and add anything we find
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;
		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			archName = i->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
		}
	}

	
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	Ogre::ResourceGroupManager::getSingleton().loadResourceGroup("General");

	//Note that creating the PlayState like this means the memory for it will "leak", since the GSM never
	//deletes it. This is fine for now, since PlayState exists for the entire duration of the app,
	//so the OS will delete it automatically when we exit.
	MenuState* menuState = new MenuState();
	m_GSM.AddState(menuState);
	PlayState* playState = new PlayState(m_pViewport, m_pKeyboard, m_pMouse);
	m_GSM.AddState(playState);
	menuState->setPlayStatePtr(playState);

	m_pTimer = new Ogre::Timer();
	m_pTimer->reset();

	m_Running = true;
	return true;
}

void Game::Run()
{
	double deltaTime = 1;
	double startTime = 0;

	m_GSM.ChangeState(0);

	while (m_Running)
	{
		m_pKeyboard->capture();
		m_pMouse->capture();
		startTime = m_pTimer->getMillisecondsCPU();
		//check input
		//run active gamestate
		m_GSM.RunActiveStates(deltaTime);
		//update graphics
		m_pRoot->renderOneFrame();
		Ogre::WindowEventUtilities::messagePump();
		deltaTime = m_pTimer->getMillisecondsCPU() - startTime;
	}
}

bool Game::keyPressed(const OIS::KeyEvent &keyEventRef)
{
	if (m_pKeyboard->isKeyDown(OIS::KC_ESCAPE) && m_GSM.GetActiveState() == 0)
		Exit();

	return m_GSM.InjectKeyPressed(keyEventRef);

}

bool Game::keyReleased(const OIS::KeyEvent &keyEventRef)
{
	return m_GSM.InjectKeyReleased(keyEventRef);
}

bool Game::mouseMoved(const OIS::MouseEvent &evt)
{
	return m_GSM.InjectMouseMoved(evt);
}

bool Game::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return m_GSM.InjectMousePressed(evt, id);
}

bool Game::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return m_GSM.InjectMouseReleased(evt, id);
}
